<?php
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;
use app\index\model\Order;
use app\index\model\Users;
class Waxpay extends Common
{
  //微信支付 
 public function wx_pay(){
        $fee=floatval(input('price'));//报名价格
       // $fee='0.01';//报名价格
        $uid=(int)input('uid');//获取用户uid
        $activity_id=(int)input('activity_id');//获取活动id
        if(empty($fee) || empty($uid) || empty($activity_id)){
          return json(['state'=>'204','msg'=>'请求参数不足']);
        }
        $rd=$this->apply_stop($activity_id);
        if(empty($rd)){
           return json(['state'=>'203','msg'=>'活动已截至']);
        }
        $re1=Users::selOne($uid);
        if(empty($re1)){
          return json(['state'=>'202','msg'=>'用户已不存在']);
        }
        $openid =       $re1['openid'];//用户的openid
     
        //商户订单号
        $order_sn=$this->order_number($openid);
        //print_r($order_sn);die;
         $sdata=['uid'=>$uid,'activity_id'=>$activity_id,'price'=>$fee,'order_sn'=>$order_sn,'order_status'=>'0','add_time'=>date("Y-m-d H:i:s")];
        //判断用户是否创建过订单
        $rs=Order::orderSet($uid,$activity_id,$sdata);
        if(empty($rs)){
          $rs=Order::orderAdd($sdata);
        }
        //活动下单
         if(!empty($rs)){
           //查询订单
        $user_order=Db::name('user_order')->where(['uid'=>$uid,'activity_id'=>$activity_id,'price'=>$fee,'order_status'=>0])->find();
      //  print_r($user_order);die;
        $fee =0.01;//举例充值0.01
        $appid =        'wx03c204fa32417649';//appid
        $body =        '单身酷玩活动报名';// '金邦汇商城';//'【自己填写】'
        $mch_id =       '1504173531';//'你的商户号【自己填写】'
        $nonce_str =    $this->nonce_str();//随机字符串
        $notify_url =   'https://www.danshenkuwan.com/api/moblie/callback';//回调的url【自己填写】';
        // $openid =       'o2qPl5dOJ-BNBMvmaw7tTPpO6-yw';//'用户的openid【自己填写】';
        $out_trade_no =$user_order['order_sn'];//商户订单号
        $spbill_create_ip =$this->get_client_ip();//'服务器的ip【自己填写】';
        $total_fee =    $fee*100;//因为充值金额最小是1 而且单位为分 如果是充值1元所以这里需要*100
        $trade_type = 'JSAPI';//交易类型 默认
        //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
         $post['appid'] = $appid;
        $post['body'] = $body;
        
        $post['mch_id'] = $mch_id;
      
        $post['nonce_str'] = $nonce_str;//随机字符串
      
        $post['notify_url'] = $notify_url;
      
        $post['openid'] = $openid;
      
        $post['out_trade_no'] = $out_trade_no;
      
        $post['spbill_create_ip'] = $spbill_create_ip;//终端的ip
      
        $post['total_fee'] = $total_fee;//总金额 最低为一块钱 必须是整数
     
        $post['trade_type'] = $trade_type;
        $sign = $this->sign($post);//签名
      //  print_r($post);die;
        $post_xml = '<xml>
           <appid>'.$appid.'</appid>
           <body>'.$body.'</body>
           <mch_id>'.$mch_id.'</mch_id>
           <nonce_str>'.$nonce_str.'</nonce_str>
           <notify_url>'.$notify_url.'</notify_url>
           <openid>'.$openid.'</openid>
           <out_trade_no>'.$out_trade_no.'</out_trade_no>
           <spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
           <total_fee>'.$total_fee.'</total_fee>
           <trade_type>'.$trade_type.'</trade_type>
           <sign>'.$sign.'</sign>
        </xml> ';
        //统一接口prepay_id
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $xml = $this->http_request($url,$post_xml);
        $array = $this->xml($xml);//全要大写
        if($array['RETURN_CODE'] == 'SUCCESS' && $array['RESULT_CODE'] == 'SUCCESS'){
           $time = time();
            $tmp='';//临时数组用于签名
            $tmp['appId'] = $appid;
            $tmp['nonceStr'] = $nonce_str;
            $tmp['package'] = 'prepay_id='.$array['PREPAY_ID'];
            $tmp['signType'] = 'MD5';
            $tmp['timeStamp'] = "$time";
             $data['state'] = 1;
            $data['timeStamp'] = "$time";//时间戳
            $data['nonceStr'] = $nonce_str;//随机字符串
            $data['signType'] = 'MD5';//签名算法，暂支持 MD5
            $data['package'] = 'prepay_id='.$array['PREPAY_ID'];//统一下单接口返回的 prepay_id 参数值，提交格式如：prepay_id=*
            $data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
            $data['out_trade_no'] = $out_trade_no;
        }else{
            $data['state'] = 0;
            $data['text'] = "错误";
            $data['RETURN_CODE'] = $array['RETURN_CODE'];
            $data['RETURN_MSG'] = $array['RETURN_MSG'];
        }
          // return  json($data);
          return   json(['state'=>'200','msg'=>'创建订单成功','result'=>$data]);
        }else{
           return json(['state'=>'201','msg'=>'创建订单失败再试试']);
        }
        
    }

    //判断活动是否截止报名
    function apply_stop($activity_id){
      
       $nowTime=time();
       $activity=Db::name('activity')->where(['id'=>$activity_id])->find();

       $upTo_time=$activity['upTo_time'];

       $uoTo=strtotime($upTo_time);
       if($nowTime<$uoTo){
           return 1;
       }
    }
    //异步回调数据
  public function callback(){
     $postObj1 =file_get_contents('php://input');
     $postObj = json_decode(json_encode(simplexml_load_string($postObj1, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
     //print_r($postObj);die;
    //签名验证
     $sign=$postObj['sign'];//返回的签名
    if(($postObj['total_fee'])&&($postObj['result_code']=='SUCCESS')){
      unset($postObj['sign']);
      if($sign!=$this->sign($postObj)){
          $error='<xml>
         <return_code><![CDATA[FAIL]]></return_code>
         <return_msg><![CDATA[]]></return_msg>
         </xml>';
         return $error;
      }
      $osn       = $postObj['out_trade_no'];//订单号
      $total_fee = $postObj['total_fee']/100;//金额
      $time_end  = $postObj['time_end'];//支付时间
      $transaction_id=$postObj['transaction_id'];//微信支付订单号
      $re=Db::name('user_order')->where(['order_sn'=>$osn,'price'=>$total_fee,'order_status'=>'1'])->find();
      if(!empty($re)){
         $success='<xml>
          <return_code><![CDATA[SUCCESS]]></return_code>
          <return_msg><![CDATA[OK]]></return_msg>
          </xml>';
          return  $success;
      }
      Db::startTrans();//开启事务
      try{
        $sdata1=['transaction_id'=>$transaction_id,'pay_time'=>$time_end,'order_status'=>'1','total_fee'=>$total_fee];
           //修改订单
          $re=Db::name('user_order')->where(['order_sn'=>$osn,'price'=>$total_fee,'order_status'=>'0'])->update($sdata1);
          if($re){
           $order=Db::name('user_order')->where(['order_sn'=>$osn,'price'=>$total_fee,'order_status'=>'1'])->find();
          }
          // //接单表生成记录
          $data1=['create_time'=>date("Y-m-d H:i:s")];//修改用户的活动的时间
          $rd = Db::name("activity_users")->where(['uids'=>$order['uid'],'orderId'=>$order['order_id'],'activity_id'=>$order['activity_id']])->update($data1);
          if(empty($rd)){
            $data2=['uids'=>$order['uid'],'orderId'=>$order['order_id'],'activity_id'=>$order['activity_id'],'create_time'=>date("Y-m-d H:i:s")];
            Db::name('activity_users')->insert($data2);
          }
          // 提交事务
          Db::commit();    

          $success='<xml>
          <return_code><![CDATA[SUCCESS]]></return_code>
          <return_msg><![CDATA[OK]]></return_msg>
          </xml>';
          return   $success;
        } catch (\Exception $e) {
          // 回滚事务
         Db::rollback();
         $error='<xml>
         <return_code><![CDATA[FAIL]]></return_code>
         <return_msg><![CDATA[]]></return_msg>
         </xml>';
         return $error;
         
        }
      }  
    
  }
//同步回调接口
public function return_url(){
  $uid=input('uid');//用户id
  $activity_id=input('activity_id');//活动id
  $out_trade_no=input('out_trade_no');//订单号
  $total_fee=input('total_fee');//支付金额
  if(empty($uid)  || empty($out_trade_no) || empty($activity_id) || empty($total_fee)){
     return json(['state'=>'202','msg'=>'请求数据不全！']);
  }
   $order=Db::name('user_order')->where(['uid'=>$uid,'order_sn'=>$out_trade_no,'activity_id'=>$activity_id,'total_fee'=>$total_fee,'order_status'=>'1'])->find();
    if($order){
      //查询活动的群id
      $rs=Db::name('activity')->where(['id'=>$activity_id])->field('tid,captain_id')->find();
      if(!empty($rs['tid'])){
         $userInfo=Db::name('user_info')->where(['uid'=>$uid])->field('nickname,userPhoto')->find();
        if(!empty($userInfo['nickname'])){
          $sdata1=['uid'=>$uid,'nickname'=>$userInfo['nickname'],'userPhoto'=>$userInfo['userPhoto'],'genreId'=>'2','create_time'=>time()];
            //查询关注我的用户群发用户信息
         Db::name('user_message')->insert($sdata1);
        }
         $headers=$this->setHeader();
        $members=json_encode(["$uid"]);//邀请的人
        $post_data=['tid'=>$rs['tid'],'owner'=>$rs['captain_id'],'members'=>$members,'magree'=>'0','msg'=>'加群啦'];
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_URL,'http://api.netease.im/nimserver/team/add.action');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $output = curl_exec($ch);
      }
      return json(['state'=>'200','msg'=>'支付的订单正确!']);
    }else{
      return json(['state'=>'201','msg'=>'支付的订单数据有误！']);
    }
  
}
    
    //随机32位字符串
    private function nonce_str(){
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i=0;$i<32;$i++){
            $result .= $str[rand(0,48)];
        }
        return $result;
    }
    //获取当前服务器的IP
    
  function get_client_ip()
  {
    if ($_SERVER['REMOTE_ADDR']) {
      $cip = $_SERVER['REMOTE_ADDR'];
    } elseif (getenv("REMOTE_ADDR")) {
      $cip = getenv("REMOTE_ADDR");
    } elseif (getenv("HTTP_CLIENT_IP")) {
      $cip = getenv("HTTP_CLIENT_IP");
    } else {
      $cip = "unknown";
    }
    return $cip;
  }

//生成订单号
    private function order_number($openid){
        //date('Ymd',time()).time().rand(10,99);//18位
        return md5($openid.time().rand(10,99));//32位
    }
    //签名 $data要先排好顺序
    public function sign($data)
    {
        $stringA = '';
        foreach ($data as $key => $value) {
            if (!$value) continue;
            if ($stringA) $stringA .= '&' . $key . "=" . $value;
            else $stringA = $key . "=" . $value;
        }
        $wx_key = 'djkaljgDJKLIP896790878r9w07r7900';//申请支付后有给予一个商户账号和密码，登陆后自己设置key
        $stringSignTemp = $stringA . '&key=' . $wx_key;//申请支付后有给予一个商户账号和密码，登陆后自己设置key 
      return strtoupper(md5($stringSignTemp));
    }
    //curl请求啊
        function http_request($url, $data = null, $headers = array())
        {
            $curl = curl_init();
            if (count($headers) >= 1) {
                curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
            }
            curl_setopt($curl, CURLOPT_URL, $url);

            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

            if (!empty($data)) {
                curl_setopt($curl, CURLOPT_POST, 1);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($curl);
            curl_close($curl);
            return $output;
        }
        //获取xml
        private function xml($xml){
          $p = xml_parser_create();
          xml_parse_into_struct($p, $xml, $vals, $index);
          xml_parser_free($p);
          $data = "";
          foreach ($index as $key=>$value) {
              if($key == 'xml' || $key == 'XML') continue;
              $tag = $vals[$value[0]]['tag'];
              $value = $vals[$value[0]]['value'];
              $data[$tag] = $value;
          }
          return $data;
        }
        /**
   xml转成数组
   */
    function xmlstr_to_array($xmlstr) {
      $doc = new \DOMDocument();
      $doc->loadXML($xmlstr);
      return $this->domnode_to_array($doc->documentElement);
    }
  }         